/**
 * Clase Defun.java
 * @author Paola Garcia 10205, Diego Yon 10070, Claudia Grajeda 10118
 * Algoritmos y estructura de datos
 * Fecha de entrega: 21 noviembre 2011
 */


public class Defun {
	public String nombre;
	public String[] parametros, param2;
	public String cadena_ins, cadena_pam;
	public Operacion operacion;
	public String operador, instruccion, operando;
	public char[] cadena;
	public int inicio, ultimo, num, parentesis, letra1, letra2, contador;
	
	double resultado;
	String operandos = "";
	double[] operandos2;
	String[] nombre_defun = new String[20];
	int[] num_param = new int[20];
	Aritmeticas aritmetica;
	Parentesis parentesis1;
	Defun defun;
	Defun[] defun0 = new Defun[20];
	boolean mayor, igual, seguir;
	
	/**
	 * Clase constructora
	 * @param ins
	 */
	
	public Defun(String ins){
		cadena = new char [ins.length()];
		cadena = ins.toCharArray();
		//obtener el nombre de la funcion a definir
		for (int pos = 0; pos < ins.length(); pos++){
			if(cadena[pos] == '('){
				nombre = ins.substring(0,pos);
				System.out.println(nombre.toUpperCase());
				ins = ins.substring(pos);
				cadena = ins.toCharArray();
				pos = ins.length();
				
			}
		}
		
		//obtener el numero de parametros, no c necesitan los parametros		
		for (int pos= 1; pos < ins.length(); pos++ ){
			if ((cadena[pos]) == ' ' ){
				
				num++;
			}
			if ((cadena[pos]) == ')'){
				num++;
				//obtener la cadena de operacion
				cadena_pam = ins.substring(0, pos+2);
				cadena_ins = ins.substring(pos+2,(ins.length()-1));
				pos = ins.length();
						
			}
		}
		//buscar los parametros en la cadena_ins
		//guardar los valores donde tienen que ser sustituidos 
	
		parametros = new String[num]; //numero de operandos
		param2 = new String[num];
		//ingresando parametros en vector
		int pos2 = 0;
		int pos3 = 1;
		cadena = cadena_pam.toCharArray();
		for (int pos =0; pos2<num ;pos++){
			if (cadena[pos] == ' ' || cadena[pos] == ')'){
				parametros[pos2] = cadena_pam.substring(pos3,pos);
				pos2++;
				pos3 = pos + 1;
			}
		}
	}
	
	/**
	 * Metodo que agarra el nombre ingresado
	 * @return String
	 */
	public String getNombre(){
		return nombre;
	}
	
	/**
	 * Metodo que agarra el numero ingresado 
	 * @return int
	 */
	public int getNum(){
		return num;
	}

	/**
	 * Metodo que define los parametros ingresados
	 * @param ins
	 */
	public void setParametros(String ins){

		//pasamos los parametros de entrada a vector param2
		//ingresando parametros en vector
		int pos2 = 0;
		int pos3 = 1;
		cadena = ins.toCharArray();
		for (int pos =1; pos2<num ;pos++){
			if (cadena[pos] == ' ' || cadena[pos] == ')'){
				param2[pos2] = ins.substring(pos3,pos);
				pos2++;
				pos3 = pos + 1;
			}
		
		}

		
		//buscar parametros[pos] = cadena_ins
				//sustuir cadena[pos] por param2[num1]
		int len;
		
		for(int num1 = 0; num1<num;num1++){
			len = parametros[num1].length();
			//pos2 = len+1;
			for(int pos = len; pos<cadena_ins.length(); pos++){
				if(cadena_ins.substring(pos-len,pos).compareTo(parametros[num1]) == 0 && num1 == 0){
					instruccion = cadena_ins.substring(0,pos-len) + param2[num1]+cadena_ins.substring(pos);
				}
				if(cadena_ins.substring(pos-len,pos).compareTo(parametros[num1]) == 0 && num1 > 0){
					instruccion = instruccion.substring(0,pos-len) + param2[num1]+instruccion.substring(pos);
				}
			}
		}
		
		cadena = instruccion.toCharArray();
		
		parentesis = 0;
		//numero de operaciones a realizar, se cuenta numero de parentesis
		for (letra1 = 0; letra1 < instruccion.length(); letra1++){
			if (cadena[letra1] == ')'){
				parentesis++;
			}
		}
		
		if (parentesis > 1){
			do{ 
				parentesis1 = new Parentesis(instruccion, parentesis);
				instruccion = parentesis1.instruccion_unica();
				parentesis--;
				cadena = instruccion.toCharArray();
			
			}while(parentesis != 1);
			
		}
	
		 
		if(parentesis == 1){
			//obtener la cadena de la operacion, longitud de la cadena que representa la operacion
			for (letra1 = 0; letra1 < instruccion.length(); letra1++ ){
				if ((cadena[letra1]) == ' ' ){
					contador = letra1;
				letra1 = instruccion.length();
				}
			}
			
			operando = instruccion.substring(1,contador);
			
			//obtener el resto de la instruccion sin el operando principal
			instruccion = instruccion.substring(contador,instruccion.length());
			letra2 = contador++;
		
			if((operando.compareTo("+")) == 0 || (operando.compareTo("-") == 0)
					|| operando.compareTo("*") == 0 || operando.compareTo("/") == 0
					|| operando.compareTo(">") == 0 || operando.compareTo("<") == 0
					|| operando.compareToIgnoreCase("EQUAL") == 0 || operando.compareTo(">=") == 0
					|| operando.compareTo("<=") == 0){
		
					contador = 0;
					
					//numero de operadores
					for (letra1= letra2; letra1 < instruccion.length(); letra1++ ){
						if ((cadena[letra1]) == ' ' ){
							contador++;
						}
					}	
					
					if (operando.compareToIgnoreCase("EQUAL") == 0 || operando.compareTo("=") == 0 || 
							operando.compareTo("<=") == 0 || operando.compareTo(">=") == 0){
						operandos = instruccion.substring(1);
					}
					
					else {
						letra2--;
						operandos = instruccion.substring(letra2,instruccion.length());
					}
				
					aritmetica = new Aritmeticas (operandos, contador);
					operandos2 = new double[contador];
					operandos2 = aritmetica.VectorOpernados();
					
					if (operando.compareTo("+") == 0){
						resultado = aritmetica.sumar(operandos2);
						System.out.println(resultado);
					}
					if (operando.compareTo("-") == 0){
						resultado = aritmetica.restar(operandos2);
						System.out.println(resultado);
					}
					if (operando.compareTo("*") == 0){
						resultado = aritmetica.multiplicar(operandos2);
						System.out.println(resultado);
					}
					if (operando.compareTo("/") == 0){
						resultado = aritmetica.dividir(operandos2);
						System.out.println(resultado);
					}
					if (operando.compareTo("<") == 0){
						mayor = aritmetica.comparar_menor(operandos2);
						if (mayor)
							System.out.println("T");
						else
							System.out.println("NIL");
					}
					if (operando.compareTo(">") == 0){
						mayor = aritmetica.comparar_mayor(operandos2);
						if (mayor)
							System.out.println("T");
						else
							System.out.println("NIL");
					}
					
					if (operando.compareTo(">=") == 0){
						mayor = aritmetica.comparar_mayor_igual(operandos2);
						if (mayor)
							System.out.println("T");
						else
							System.out.println("NIL");
					}
					
					if (operando.compareTo("<=") == 0){
						mayor = aritmetica.comparar_menor_igual(operandos2);
						if (mayor)
							System.out.println("T");
						else
							System.out.println("NIL");
					}
					
					if(operando.compareToIgnoreCase("EQUAL") == 0 || operando.compareTo("=") == 0){
					      igual = aritmetica.equal(operandos2);
					      if(igual)
					       System.out.println("T");
					      else
					       System.out.println("NIL");
					      
					}
				}
			else{	
					cadena = instruccion.toCharArray();
					letra2 = contador;
					contador = 0;
					
					//numero de operadores
					for (letra1= 0; letra1 < instruccion.length(); letra1++ ){
						if ((cadena[letra1]) == ' ' ){
							contador++;
						}
					}	
					//revisar si tiene el numero de parematros indicado
					for (int pos=0; pos<20;pos++){//obtener la posicion de la funcion en el vector
						
						if (nombre_defun[pos].compareToIgnoreCase(operando) == 0 ){									
							if(num_param[pos] == contador){
								defun0[pos].setParametros(instruccion);
								
								
								seguir = false;
							}
							else{
								System.out.println("error");
								seguir = false;
							}
							
							
							pos = 20;
						}
					}
			}
		}
	}
}